#include "stdafx.h"
#include "libraries.h"

#include "Application.h"
#include "Filesystem.h"
#include "DefaultGUIStyle.h"

#include "Demo.h"

#include "TriFractal.h"
#include "Cave.h"
#include "Tunnel.h"

#include "DisplayModeDialog.h"

using namespace Cvekas;

const float width = 1024.0f;
const float height = 576.0f;
const bool show_tweaks = false;

class Delirium: public Application
{
public:
	Delirium(HINSTANCE instance, const std::string& name, const std::string& log_filename)
		: Application(instance, name, log_filename)
	{
	}

	virtual ~Delirium()
	{
	}

	virtual void initVideoDevice()
	{
		DeviceCapsPtr caps = video_device->getCaps(D3DDEVTYPE_HAL);
		if(caps->getPSVersion() < DeviceCaps::ps2_0 || caps->getVSVersion() < DeviceCaps::vs2_0)
		{
			MessageBox(NULL, "Your graphics card sucks.", "ERROR", MB_OK);
			return;
		}

		settings->insert("video", VideoSettings());
		VideoSettings& video_settings = static_cast<VideoSettings&>((*settings)["video"]);

		if(!showDisplaymodeDialog(video_device->getModes(), video_settings))
			return;

		window = WindowPtr(new Window(instance, name));
		window->showCursor(false);
		video_device->init(window);
		video_device->setProjectionMatrix(Matrix::perspective(pi / 4.0f, width / height, 0.1f, 50.0f));
		video_device->setAspectRatio(width / height);
	}

	virtual void init()
	{
		SoundPtr soundtrack = sound_manager->loadStream("GeriauGrotiPavalgiusiam", 
			Filesystem::redirect("geriau groti pavalgiusiam.ogg"));
		
		vector_batch = VectorBatchPtr(new VectorBatch(main_renderer, (uint)width, (uint)height));
		sprite_batch = SpriteBatchPtr(new SpriteBatch(main_renderer, (uint)width, (uint)height));

		demo = DemoPtr(new Demo(soundtrack));

		TriFractalPtr tri_fractal(new TriFractal(main_renderer, vector_batch, sprite_batch));
		CavePtr cave(new Cave(main_renderer, vector_batch));
		TunnelPtr tunnel(new Tunnel(main_renderer, vector_batch));

		demo->add(0, 0.0f, 10.8f, tri_fractal);
		demo->add(0, 11.0f, 40.0f, cave);
		demo->add(0, 40.2f, 74.0f, tunnel);
		
		demo->seal();

		//demo->play();
		//demo->setTime(40.1f);
	}

	virtual bool update()
	{
		// Delay starting demo by 2 seconds
		static bool is_playing = false;
		if(!is_playing && Timer::getTimeMs() > 2000.0f)
		{
			is_playing = true;
			demo->play();
		}
		
		input->getKeyboard()->update();
		input->getMouse()->update();
		
		return demo->update();
	}

	virtual bool render()
	{
		bool result = demo->render();
		return result;
	}
private:
	DemoPtr demo;

	VectorBatchPtr vector_batch;
	SpriteBatchPtr sprite_batch;
};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nShowCmd)
{
	try
	{
		Filesystem::init("delirium_data\\");
		Delirium app(hInstance, "Delirium", Filesystem::redirect("Delirium.log"));
		app.run();
	}
	catch (std::exception& e)
	{
		MessageBox(NULL, e.what(), "Fatal error", NULL);
	}
	return 0;
}
